﻿using IceDog.WebApi.AnythingApi.Mapping;
using IceDog.WebApi.AnythingApi.Models.Results;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;

namespace IceDog.WebApi.AnythingApi.Controllers
{
    /// <summary>
    /// 文件
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class FileController : ControllerBase
    {
        private readonly ILogger<FileController> _logger;
        private readonly IWebHostEnvironment _env;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logger"></param>
        public FileController(ILogger<FileController> logger, IWebHostEnvironment env)
        {
            _logger = logger;
            _env = env;
            _logger.LogInformation("Create Instance Of FileController");
        }

        /// <summary>
        /// 检测上传文件路径，没有就建上
        /// </summary>
        private string GetPath()
        {
            var path = Path.Combine(_env.WebRootPath, "files");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            return path;
        }

        /// <summary>
        /// 获取文件列表
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("[action]")]
        public IActionResult GetFileList()
        {
            var path = GetPath();
            var files = Directory.GetFiles(path).ToList().Select(p => Path.GetFileName(p));
            return Ok(files);
        }

        /// <summary>
        /// 上传单个文件
        /// </summary>
        /// <returns></returns>
        [HttpPost, Route("[action]")]
        public IActionResult UploadFile(IFormFile file)
        {
            var path = GetPath();
            var fileInfo = new FileInfo(Path.Combine(path, file.FileName));
            var fs = fileInfo.OpenWrite();
            file.CopyTo(fs);
            fs.Flush();
            fs.Close();
            return Ok(true);
        }

        /// <summary>
        /// 上传多个文件
        /// </summary>
        /// <returns></returns>
        [HttpPost, Route("[action]")]
        public IActionResult UploadFiles([FromForm]IFormFileCollection files)
        {
            var path = GetPath();
            foreach (var file in files)
            {
                var fileInfo = new FileInfo(Path.Combine(path, file.FileName));
                var fs = fileInfo.OpenWrite();
                file.CopyTo(fs);
                fs.Flush();
                fs.Close();
            }
            return Ok(true);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        [HttpGet, Route("[action]")]
        public IActionResult DownloadFile(string fileName)
        {
            var path = GetPath();
            path = Path.Combine(path, fileName);
            var contentType = "application/octet-stream";
            return PhysicalFile(path, contentType, fileName);
        }

        /// <summary>
        /// 查看文件,无法查看的会进行下载
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        [HttpGet, Route("[action]")]
        public IActionResult ViewFile(string fileName)
        {
            var path = GetPath();
            path = Path.Combine(path, fileName);
            if (System.IO.File.Exists(fileName))
            {
                return BadRequest();
            }
            var contentType = ContentTypeHelper.GetMimeType(Path.GetExtension(fileName));
            return PhysicalFile(path, contentType, fileName);
        }

        /// <summary>
        /// 返回文件 Apple.txt 的内容
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("GetAppleTxt")]
        public ActionResult GetAppleTxt()
        {
            var file = new FileInfo("wwwroot/files/apple.txt");
            return PhysicalFile(file.FullName, "text/plain");
        }

        /// <summary>
        /// 创建 txt 文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        [HttpGet, Route("[action]")]
        public IActionResult CreateTxtFile(string fileName,string content)
        {
            var path = GetPath();
            path = Path.Combine(path, fileName);
            System.IO.File.WriteAllText(path, content);
            return Ok();
        }

        /// <summary>
        /// 返回文件 Apple.html 的内容
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("GetAppleHtml")]
        public ActionResult GetAppleHtml()
        {
            var file = new FileInfo("wwwroot/files/apple.html");
            return PhysicalFile(file.FullName, "text/html");
        }

        /// <summary>
        /// 返回文件 Apple.xml 的内容
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("GetAppleXml")]
        public ActionResult GetAppleXml()
        {
            var file = new FileInfo("wwwroot/files/apple.xml");
            return PhysicalFile(file.FullName, "text/xml");
        }

        //        [HttpGet, Route("DownloadFile/{fileName}")]
        //        public async Task<IActionResult> Download(string fileName)
        //        {
        //            var result = new CommonResult<string>();
        //            string filePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "files", fileName);
        //#if DEBUG
        //            string webRootPath = _env.WebRootPath;
        //            filePath = Path.Combine(webRootPath, "files", fileName);
        //#endif
        //            if (!System.IO.File.Exists(filePath))
        //            {
        //                return NotFound(new
        //                {
        //                    code = 0,
        //                    message = $"文件 [{filePath}] 不存在"
        //                });
        //            }
        //            //这就是ASP.NET Core循环读取下载文件的缓存大小，这里我们设置为了1024字节，
        //            //也就是说ASP.NET Core每次会从下载文件中读取1024字节的内容到服务器内存中，
        //            //然后发送到客户端浏览器，这样避免了一次将整个下载文件都加载到服务器内存中，导致服务器崩溃
        //            int bufferSize = 1024;
        //            //由于我们下载的是一个gz文件，所以设置ContentType为application/x-gzip
        //            Response.ContentType = "text/plain";
        //            //在Response的Header中设置下载文件的文件名，这样客户端浏览器才能正确显示下载的文件名，
        //            //注意这里要用HttpUtility.UrlEncode编码文件名，否则有些浏览器可能会显示乱码文件名
        //            var contentDisposition = "attachment;" + "filename=" + HttpUtility.UrlEncode(fileName);
        //            Response.Headers.Add("Content-Disposition", new string[] { contentDisposition });

        //            //使用FileStream开始循环读取要下载文件的内容
        //            using (FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
        //            {
        //                //调用Response.Body.Dispose()并不会关闭客户端浏览器到ASP.NET Core服务器的连接，之后还可以继续往Response.Body中写入数据
        //                using (Response.Body)
        //                {
        //                    long contentLength = fs.Length;//获取下载文件的大小
        //                    if (contentLength > 10485760) //大于10M
        //                    {
        //                        bufferSize = 1048576;//一次读取1M的内容
        //                    }
        //                    Response.ContentLength = contentLength;//在Response的Header中设置下载文件的大小，这样客户端浏览器才能正确显示下载的进度

        //                    byte[] buffer;
        //                    long hasRead = 0;//变量hasRead用于记录已经发送了多少字节的数据到客户端浏览器

        //                    //如果hasRead小于contentLength，说明下载文件还没读取完毕，继续循环读取下载文件的内容，并发送到客户端浏览器
        //                    while (hasRead < contentLength)
        //                    {
        //                        //HttpContext.RequestAborted.IsCancellationRequested可用于检测客户端浏览器和ASP.NET Core服务器之间的连接状态，
        //                        //如果HttpContext.RequestAborted.IsCancellationRequested返回true，说明客户端浏览器中断了连接
        //                        if (HttpContext.RequestAborted.IsCancellationRequested)
        //                        {
        //                            //如果客户端浏览器中断了到ASP.NET Core服务器的连接，这里应该立刻break，取消下载文件的读取和发送，避免服务器耗费资源
        //                            break;
        //                        }

        //                        buffer = new byte[bufferSize];

        //                        int currentRead = await fs.ReadAsync(buffer, 0, bufferSize);//从下载文件中读取bufferSize(1024字节)大小的内容到服务器内存中

        //                        await Response.Body.WriteAsync(buffer, 0, currentRead);//发送读取的内容数据到客户端浏览器
        //                        await Response.Body.FlushAsync();//注意每次Write后，要及时调用Flush方法，及时释放服务器内存空间

        //                        hasRead += currentRead;//更新已经发送到客户端浏览器的字节数
        //                    }
        //                }
        //            }
        //            return Ok(new
        //            {
        //                code = 1,
        //                message = $"文件 [{filePath}] 存在"
        //            });
        //        }
    }
}